#pragma once

#define _GNU_SOURCE
#include <strings.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <stddef.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#include <math.h>

#include "znx_config.h"

#define ZNX_INT32_LEN                           (sizeof("-2147483648") - 1)
#define ZNX_INT64_LEN                           (sizeof("-9223372036854775808") - 1)

#define ZNX_MAXHOSTNAMELEN                      256
#define ZNX_MAX_UINT32_VALUE                    (uint32_t) 0xffffffff
#define ZNX_MAX_INT32_VALUE                     (uint32_t) 0x7fffffff

typedef uint8_t                                 znx_bool_t;
#define ZNX_FALSE                               0
#define ZNX_TRUE                                1

#define ZNX_BOOL_UNSET                          (znx_bool_t)(-1)
#define ZNX_INT_UNSET                           (-1)
#define ZNX_INT64_UNSET                         (-1)
#define ZNX_UINT64_UNSET                        (uint64_t)(-1)
#define ZNX_SIZET_UNSET                         (size_t)(-1)
#define ZNX_PTR_UNSET                           (void *)(-1)

typedef int64_t                                 znx_result_t;
#define ZNX_SUCCESS                             0
// -0 ~ -999 for syscall errno
// -----------------------------------------------
// -1000 ~ -1999 is znx result errno
#define ZNX_FAILED                              (-1001)
#define ZNX_TIMEOUT                             (-1002)
#define ZNX_AGAIN                               (-1003)
#define ZNX_EOF                                 (-1004)
// -2000 ~ -2999 is znx http errno
#define ZNX_HTTP_ERRNO_START                    (-2000)
// ~9000 ~ -9999 is other errno
#define ZNX_AIO_LOOP_STOP_ERRNO                 (-9000)

#define INVALID_FD                              -1

#define LF                                      '\n'
#define CR                                      '\r'
#define CRLF                                    "\r\n"
#define CRLF_LEN                                2

#define ZNX_ABS(value)                          (((value) >= 0) ? (value) : - (value))
#define ZNX_SWAP(a, b, tmp)                     {tmp=a; a=b; b=tmp;}
#define ZNX_MAX(val1, val2)                     ((val1 < val2) ? (val2) : (val1))
#define ZNX_MIN(val1, val2)                     ((val1 > val2) ? (val2) : (val1))

#define ZNX_ALIGN(d, a)                         (((d) + (a - 1)) & ~(a - 1))
#define ZNX_ALIGN_PTR(p, a)                     \
    (u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))

#define ZNX_PAGE_BITS                           12                      // 4K
#define ZNX_PAGE_SIZE                           (1 << ZNX_PAGE_BITS)    // 1 << 12 = 4K
#define ZNX_PAGE_MASK                           (ZNX_PAGE_SIZE - 1)     // 4K - 1

#define ZNX_ALIGN_PAGE_SIZE(size)               \
    ((size + ZNX_PAGE_MASK) & (~ZNX_PAGE_MASK))

#define ZNX_IS_PAGE_ALIGNED(size)               \
    ((size&ZNX_PAGE_MASK) == 0)


#define ZNX_SCHED_YIELD                         usleep(1)

#define ZNX_CASTBIT(val, width)                 ((val) & ((1ULL << width) - 1))


#define DD(fmt, args...)                        \
    printf(fmt, ##args); printf("\n")

#define DD_FATAL(fmt, args...)                  \
    printf(fmt, ##args); printf("\n"); abort()


#define ZNX_ASSERT_FATAL(msg)                   \
    assert(msg == NULL)


#define likely(x)                               __builtin_expect(!!(x), 1)
#define unlikely(x)                             __builtin_expect(!!(x), 0)
